#ifndef VIEWMATRIX_H_
#define VIEWMATRIX_H_

#include <GL/glew.h>

#include <stack>

#include "definitions.h"

class CMat4
{

	private:

		float m_Translate[3];
		float m_Scale[3];

	public:
		
		CMat4() 
		{
			
			Identity();
			
		}

		void Identity()
		{
			

			for( int j = 0; j < 3; j++ )
			{
				
				m_Translate[j] = 0.0f;
				m_Scale[j] = 1.0f;
				
			}

		}
		
		void Translate( float x, float y, float z )
		{
			
			m_Translate[0] += ( int )( x * m_Scale[0] );
			m_Translate[1] += ( int )( y * m_Scale[1] );
			m_Translate[2] += ( int )( z * m_Scale[2] );
			
		}
		
		void Scale( float x, float y, float z )
		{
			
			m_Scale[0] *= x;
			m_Scale[1] *= y;
			m_Scale[2] *= z;
			
		}
		
		float * GetTranslate()
		{
			
			return m_Translate;
			
		}
		
		float * GetScale()
		{
			
			return m_Scale;
			
		}
		
		bool PointInScreen( double x, double y )
		{
			
			if( x < 0 || x >= SCREEN_WIDTH ||
				y < 0 || y >= SCREEN_HEIGHT )
				return false;
			
			return true;
			
		}
		
		bool CurQuadInScreen()
		{
			
			double x = m_Translate[0];
			double y = m_Translate[1];
			
			return ( PointInScreen( x, y ) || PointInScreen( x + m_Scale[0], y ) || PointInScreen( x + m_Scale[0], y + m_Scale[1] ) || PointInScreen( x, y + m_Scale[1] ) );
			
		}

};

class CViewMatrix
{
	
private:

	std::stack< CMat4 > m_vMats;
	
public:
	
	CViewMatrix()
	{
		
		m_vMats.push( CMat4() );
		
	}
	
	bool CurQuadInScreen()
	{
		
		return m_vMats.top().CurQuadInScreen();
		
	}
	
	float * GetTranslate()
	{
		
		m_vMats.top().GetTranslate();
		
	}
	
	void BindToGLSLUniform( GLuint transattrib, GLuint scaleattrib )
	{
		
		glUniform4fv( transattrib, 1, m_vMats.top().GetTranslate() );
		glUniform4fv( scaleattrib, 1, m_vMats.top().GetScale() );
		
	}
	
	void LoadIdentity()
	{
		
		int size = m_vMats.size();
		
		if( size > 1 )
		{
			--size;
			
			for( int j = 0; j < size; j++ )
				m_vMats.pop();
			
		}
		
		m_vMats.top().Identity();
		
	}
	
	void Translate( float x, float y, float z )
	{
		
		m_vMats.top().Translate( x, y, z );
		
	}
	
	void Scale( float x, float y, float z )
	{
		
		m_vMats.top().Scale( x, y, z );
		
	}
	
	void Push()
	{
		
		m_vMats.push( m_vMats.top() );
		
	}
	
	void Pop()
	{
		
		if( m_vMats.size() > 1 )
			m_vMats.pop();
		
	}

};

#endif